/*global pi */
var basic01 = (function () {
	"use strict";

	var module = {},
		ANI = {IDLE: 0, RUN: 1, ATTACH: 2};

	/* 创建一个演示程序 */
	module.createDemo = function () {
		var demo = {},
			scene,
			camera,
			camsys,
			dragStart,
			player,
			lastTime,
			terrainQuery,
			collisionQuery,
			getClientSize,
			MASK_PLAYER = 0,
			MASK_NPC = 0,
			MASK_BOX = 0,
			collisionSolver,
			onMouseDown = function (event) { // 鼠标按键按下
				var t, pos, ray,
					x = event.offsetX,
					y = event.offsetY;

				switch (event.button) {
				case 0: // 左键
					dragStart = {x: x, y: y};
					break;
				case 2: // 右键
					ray = camera.getRay(x / getClientSize().w, y / getClientSize().h);
					pos = terrainQuery(ray).pos;
					pos.y += 5;
					t = player.phyMod.movePath([player.phyMod.getPos(), pos], 0.005, true, true);
					player.turnTo(pos, true, 300);
					player.playAni([{ani: ANI.RUN, time: 0, shiftTime: 250}, {ani: ANI.IDLE, time: t - 250, shiftTime: 500}]);
					break;
				}
			},
			onMouseUp = function (event) { // 鼠标按键弹起
				switch (event.button) {
				case 0: // 左键
					dragStart = undefined;
					break;
				case 2: // 右键
					break;
				}
			},
			onMouseMove = function (event) { // 鼠标移动
				var dx, dy;
				if (dragStart === undefined) {
					return;
				}

				dx = event.offsetX - dragStart.x;
				dy = event.offsetY - dragStart.y;
				if (dx === 0 && dy === 0) {
					return;
				}

				dragStart = {x: event.offsetX, y: event.offsetY};
				camsys.rotate(dx / 150);
				camsys.pullup(dy / 150);
			},
			onMouseWheel = function (event) { // 鼠标滚轮
				var dist = event.wheelDelta / 1000 * camsys.getDistance();
				camsys.push(-dist);
			},
			onKeyDown = function (event) { // 键盘按键响应
				var kc = event.keyCode, i, fan, pos, lst, pts = [],
					fanQuery = pi.scene.query.createSectorQuery(scene, MASK_BOX),
					fun = function (movObj) {
						var pos = movObj.getPos(),
							time = 0,
							rollAxis = {},
							dir = {};
						pi.math.vec3.sub(dir, pos, player.getPos());
						pi.math.vec3.normalize(dir, dir);
						pi.math.vec3.cross(rollAxis, {x: 0, y: 1, z: 0}, dir);
						pi.math.vec3.normalize(rollAxis, rollAxis);
						return function (obj, timeElapsed) {
							var offset = {}, speed, dq = {}, quat;
							time += timeElapsed;
							if (time >= 2000) {
								return false;
							}

							speed = 3 * (1 - time / 2000);
							pi.math.vec3.scale(offset, dir, timeElapsed * speed / 1000);
							pi.math.vec3.add(pos, pos, offset);
							obj.setPos(pos);

							pi.math.quat.fromAxisAngle(dq, rollAxis, pi.math.vec3.length(offset));
							quat = obj.getOrient();
							pi.math.quat.mul(quat, quat, dq);
							obj.setOrient(quat);
							return true;
						};
					};

				switch (kc) {
				case 65: // a - 攻击
					player.stopMove();
					player.playAni([{ani: ANI.ATTACH, time: 0, shiftTime: 100}, {ani: ANI.IDLE, time: 800, shiftTime: 100}]);
					fan = scene.createSector(2, Math.PI / 4, {r: 128, g: 255, b: 0, a: 64});
					fan.translucent = true;
					fan.setVisible(true);
					pos = player.getPos();
					fan.setPos({x: pos.x, y: pos.y + 0.5, z: pos.z});
					fan.setOrient(player.getOrient());
					fan.time = 0;
					pi.scene.movement.create(fan, function (obj, timeElapsed) {
						obj.time += timeElapsed;
						if (obj.time > 1000) {
							scene.destroyObj(fan);
							fan = undefined;
							return false;
						} else {
							return true;
						}
					});

					lst = fanQuery.doQuery(2, Math.PI / 4, fan.getWorldMat());
					for (i = 0; i < lst.length; i++) {
						pi.scene.movement.create(lst[i], fun(lst[i]));
					}
					break;
				case 80: // p - 打印玩家位置
					if (event.ctrlKey) { // 同时打印上一帧位置
						scene.setSnapshoot("lastFrame");
						pi.log("last pos = " + player.getPos().x + "," + player.getPos().y + "," + player.getPos().z);
						scene.setSnapshoot();
					}
					pi.log("curr pos = " + player.getPos().x + "," + player.getPos().y + "," + player.getPos().z);
					pts.push({x: player.getPos().x, z: player.getPos().z});
					break;
				case 112: // f1 - 显示/隐藏可视物体
					if (scene.renderMask & pi.scene.MASK_VISIBLE) {
						scene.renderMask &= ~pi.scene.MASK_VISIBLE;
					} else {
						scene.renderMask |= pi.scene.MASK_VISIBLE;
					}
					break;
				case 113: // f2 - 显示/隐藏障碍物
					if (scene.renderMask & pi.scene.MASK_OBSTACLE) {
						scene.renderMask &= ~pi.scene.MASK_OBSTACLE;
					} else {
						scene.renderMask |= pi.scene.MASK_OBSTACLE;
					}
					break;
				}
			},
			drawScene = function () { // 绘制场景
				if (lastTime === 0) {
					lastTime = pi.lang.createDate().getTime();
				}

				// 开始渲染，返回渲染指令缓冲区
				var now = pi.lang.createDate().getTime(),
					buf = pi.render.run.beginRender(),
					timeElapsed = now - lastTime;

				// 更新运动
				pi.scene.movement.update(timeElapsed);

				// 更新摄像机
				camsys.update(timeElapsed);

				// 更新场景
				scene.update(timeElapsed);

				// 渲染场景
				scene.render(camera, buf);

				// 发送渲染指令
				pi.render.run.endRender(buf);

				// 检测碰撞并解碰撞
				collisionQuery.doQuery(MASK_PLAYER, pi.scene.MASK_OBSTACLE, collisionSolver);

				// 制作场景快照
				scene.taskSnapshoot("lastFrame");

				lastTime = now;
			},
			doSchedule = function () { // 调度场景
				scene.scheduleArea(camera); // 调度场景
				scene.scheduleTerrain(camera); // 调度地块
			};

			// 初始化演示程序
		demo.init = function (doc) {
			pi.mod.require(["pi.lang", "pi.scene", "pi.scene.camsys", "pi.scene.query", "pi.scene.movement", "pi.res", "pi.render.run"], function () {
				pi.browser.setSize(pi.vcall.webViewHandle, 1024, 768);
				pi.render.run.init(function (context) {
					// 垃圾回收循环
					pi.lang.setInterval(pi.vcall.gc, 1000);

					MASK_PLAYER = pi.scene.MASK_USER << 1;
					MASK_NPC = pi.scene.MASK_USER << 2;
					MASK_BOX = (pi.scene.MASK_USER << 3 | pi.scene.MASK_OBSTACLE);

					// 创建场景
					pi.res.load("demos/basic01/json/scene.json",
						pi.res.JSON,
						function (jsonData) {
							var obj1, obj2, obj3, fun;

							// 加载场景
							scene = pi.scene.load(jsonData);
							scene.showAABB = false;

							// 创建摄像机
							camera = scene.createCamera();
							camera.setProjection(45.0 * Math.PI / 180, 1, 0.1, 10000);
							camsys = pi.scene.camsys.createThirdPerson(camera);

							// 创建地表高度查询器
							terrainQuery = scene.createHeightQuery();

							// 创建碰撞查询器
							collisionQuery = pi.scene.query.createCollisionPairQuery(scene);

							// 创建主角，并设置摄像机
							player = scene.createEntity({
								mesh: "demos/basic01/res/npc/npc.model",
								tex: "demos/basic01/res/npc/npc.png",
								sk: "demos/basic01/res/npc/npc.sk"
							});
							player.setAni(ANI.IDLE);
							player.setVisible(true);
							player.phyMod = scene.createCube();
							player.phyMod.setMask(MASK_PLAYER);
							player.phyMod.setScale({x: 0.75, y: 1.5, z: 0.75});
							player.phyMod.setPos({x: 32, y: 14.5, z: 32});
							pi.scene.movement.create(player, function (obj, timeElapsed) {
								player.phyMod.onGround();
								obj.setPos(obj.phyMod.getPos());
								return true;
							});

							camsys.setParams({yaw: 0, pitch: Math.PI / 8, dist: 3, offset: {x: 0, y: 1.5, z: 0}});
							camsys.setAim(player);

							// 创建几个小盒子
							obj1 = scene.createEntity({
								mesh: "demos/basic01/res/qiu/qiu.model",
								tex: "demos/basic01/res/qiu/qiu.png"
							});
							obj1.setPos({x: 40, y: 14, z: 40});
							obj1.setVisible(true);
							obj1.setMask(MASK_BOX);
							obj1.update = function () {
								obj1.onGround(1);
							};

							// 设置碰撞解决函数
							collisionSolver = function (obj1, obj2) {
								var pos;
								player.phyMod.stopMove();
								player.stopAni(ANI.IDLE);
								scene.setSnapshoot("lastFrame");
								pos = player.phyMod.getPos();
								scene.setSnapshoot();
								player.phyMod.setPos(pos);
							};

							pi.browser.resize(pi.vcall.webViewHandle);

							// 场景调度
							pi.lang.setInterval(doSchedule, 1000);

							// 设置应用层的渲染回调
							pi.render.run.setCallback(drawScene, scene.resize);
						});
				});
			});

			// 注册鼠标和键盘事件
			doc.onmousedown = onMouseDown;
			doc.onmouseup = onMouseUp;
			doc.onmousemove = onMouseMove;
			doc.onmousewheel = onMouseWheel;
			doc.onkeydown = onKeyDown;
			getClientSize = function () { return {w: doc.body.clientWidth, h: doc.body.clientHeight}; };
		};

		return demo;
	};

	return module;
}());